home *** CD-ROM | disk | FTP | other *** search
- /*
- // COMDEMO.C
- //
- // Serial communications demo program for the Cport communications library.
- //
- // Copyright (c) 1993 Bri Productions
- //
- */
-
- #include "cport.h"
- #include "xmodem.h"
- #include <conio.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <bios.h>
- #include <ctype.h>
- #include <stdio.h>
-
-
- /*
- //-------------------------------------
- //
- // Microsoft portability
- //
- //-------------------------------------
- */
- #if M_I86
-
- #include <stdarg.h>
- #include <time.h>
- #include <graph.h>
-
- #define BLUE 1
- #define LIGHTGRAY 7
-
- #define bioskey(a) _bios_keybrd(a)
- #define gotoxy(x,y) _settextposition((short)(y), (short)(x))
- #define clrscr() _clearscreen(_GWINDOW)
- #define textattr(a) _settextcolor((short)((a)&0xf)); _setbkcolor((short)((a)>>4))
- #define window(a,b,c,d) _settextwindow((short)(b),(short)(a),(short)(d),(short)(c))
- #define cputs(s) _outtext(s)
-
- int wherex (void);
- int wherey (void);
- void delay (clock_t milliseconds);
- void clreol (void);
-
- #endif
-
- /*
- //-------------------------------------
- //
- // Queue sizes and thresholds
- //
- //-------------------------------------
- */
- #define TXQ 4096
- #define RCVQ 4096
- #define THRESH (RCVQ * 3 / 4)
-
-
- /*
- //-------------------------------------
- //
- // numbers of parameters
- //
- //-------------------------------------
- */
- #define NUM_COM 4
- #define NUM_BAUD 9
- #define NUM_MODE 2
- #define NUM_HND 4
-
-
- /*
- //-------------------------------------
- //
- // scan codes
- //
- //-------------------------------------
- */
- #define A 0x1E00
- #define B 0x3000
- #define C 0x2E00
- #define D 0x2000
- #define E 0x1200
- #define F 0x2100
- #define G 0x2200
- #define H 0x2300
- #define I 0x1700
- #define M 0x3200
- #define N 0x3100
- #define O 0x1800
- #define P 0x1900
- #define R 0x1300
- #define S 0x1F00
- #define W 0x1100
- #define X 0x2D00
- #define PGDN 0x5100
- #define PGUP 0x4900
-
-
- #define COM3A PORT2|IRQ5
-
-
- /*
- //-------------------------------------
- //
- // text attributes
- //
- //-------------------------------------
- */
- #define NORM 0x07
- #define BOLD 0x08
- #define FAINT 0xF7
- #ifndef BLINK
- #define BLINK 0x80
- #endif
- #define REVRS 0x77
- #define ESC 0x1b
-
-
- /*
- //-------------------------------------
- //
- // parameter constants
- //
- //-------------------------------------
- */
- const unsigned id[] = { COM1, COM2, COM3A, COM4 };
- const int baud[] = { B115200, B57600, B38400, B19200,
- B9600, B4800, B2400, B1200, B300 };
- const byte mode[] = { W8|S1|NONE, W7|S1|EVEN };
- const byte hndshk[] = { OFF ,SOFT, HARD, HARD|SOFT };
-
- /*
- //-------------------------------------
- //
- // parameter indexes
- //
- //-------------------------------------
- */
- struct indx{
- byte id;
- byte baud;
- byte mode;
- byte ansi;
- byte hndshk;
- byte lf;
- byte echo;
- }indx = { 0, 3, 0, 1, 0, 0, 0 };
-
-
- /*
- //-------------------------------------
- //
- // parameter messages
- //
- //-------------------------------------
- */
- struct{
- char *id [NUM_COM ];
- char *baud [NUM_BAUD];
- char *mode [NUM_MODE];
- char *ansi [2];
- char *hndshk[NUM_HND];
- char *lf [2];
- }msg={
- { "COM1", "COM2", "COM3", "COM4" },
- { "115k", "57600", "38400", "19200", "9600",
- "4800", "2400", "1200", "300" },
- { "8-1-N", "7-1-E" },
- { "TTY", "ANSI" },
- { "NONE", "SOFT", "HARD", "BOTH" },
- { " ", "LF" }
- };
-
-
- /*
- //-------------------------------------
- //
- // screen coordinates
- //
- //-------------------------------------
- */
- static int x = 1; /* cursor location */
- static int y = 1;
- static byte attrib = NORM; /* present text attribute */
- #define ERR_X 41 /* error message x coordinate */
- #define STAT_X 60 /* status message x coordinate */
-
-
- /*
- //-------------------------------------
- //
- // function prototypes
- //
- //-------------------------------------
- */
- static void Init (void);
- static void Uninit (void);
- static void NewParam (void);
- static void Ansi (void);
- static void CheckError (void);
- static void CheckStatus (void);
- static void Upload (void);
- static void Download (void);
- static int callback (int msg, unsigned param);
- static void put_ch (char c);
-
-
-
- char *Xmsg[] = { "\r\ntransfer successful",
- "\r\nfile error",
- "\r\ntransfer canceled",
- "\r\nmemory error"
- };
-
- struct C_param param;
- COM com;
-
- /*
- //-------------------------------------
- //
- // main()
- //
- //-------------------------------------
- */
- void main(void)
- {
- char c;
- unsigned key;
- byte dtr = ON;
-
-
- /* initialize */
-
- Init();
-
- while(1)
- {
-
- /* Poll the keyboard buffer for available keystrokes. */
- /* Meanwhile, the receive queue is checked for available */
- /* characters, check for errors and check the modem status */
-
- while(!bioskey(1))
- {
-
- /* If a character(s) is available in the receive queue, */
- /* fetch it. If it is and escape character, it must be */
- /* check to see if it is the start of an ansi sequence. */
- /* Otherwise the cursor position is updated, and the */
- /* character is printed. */
-
- if(ComLenRx(com))
- {
- c = ComGetc(com);
-
- if(c == ESC && indx.ansi)
- {
- Ansi();
- gotoxy(x, y);
- continue;
- }
-
- put_ch(c);
-
- }
-
-
- /* Check for errors and changes in the modem status */
-
- CheckError();
- CheckStatus();
- }
-
-
- /* When a key is pressed, the key is fetched, and the */
- /* keyboard flags are checked to see if the alt key was */
- /* also pressed. If the alt key was pressed, we must */
- /* check if the key is a valid command, and if so */
- /* process it accordingly */
-
- key = bioskey(0);
- if(!(key & 0x00ff))
- {
- switch(key)
- {
-
- /* exit */
-
- case X:
- Uninit();
-
-
- /* Next com port */
-
- case C:
- ComParam(com, ¶m);
- ComClose(com);
- do
- {
- indx.id++;
- indx.id %= NUM_COM;
- param.id = id[indx.id];
- }
- while((com = ComOpenS(¶m)) == NULL);
- NewParam();
- break;
-
-
- /* Next baud rate */
-
- case B:
- indx.baud++;
- indx.baud %= NUM_BAUD;
- ComBaud(com, baud[indx.baud]);
- NewParam();
- break;
-
-
- /* Next word length */
-
- case M:
- indx.mode++;
- indx.mode %= NUM_MODE;
- ComMode(com, mode[indx.mode]);
- NewParam();
- break;
-
-
- /* Toggle ansi terminal */
-
- case A:
- indx.ansi ^= 1;
- NewParam();
- break;
-
-
- /* Next handshake scheme */
-
- case H:
- indx.hndshk++;
- indx.hndshk %= NUM_HND;
- ComHandshake(com, hndshk[indx.hndshk], THRESH);
- NewParam();
- break;
-
-
- /* Echo */
-
- case E:
- indx.echo ^= 1;
- break;
-
-
- /* Toggle LF append */
-
- case N:
- indx.lf ^= 1;
- NewParam();
- break;
-
- /* Initialize hayes modem */
-
- case I:
- ComPuts(com, "ATZ\r\n");
- break;
-
-
- /* Hayes modem dial command */
-
- case D:
- ComPuts(com, "ATDT");
- break;
-
-
- /* Hayes modem hang up command */
-
- case G:
- ComPuts(com, "+++");
- delay(3000);
- ComPuts(com, "ATH0\r\n");
- break;
-
- case PGUP:
- Upload();
- break;
-
- case PGDN:
- Download();
- break;
-
- case R:
- dtr ^= 1;
- ComDtr(com, dtr);
- break;
-
- default:
- continue;
- }
- }
-
-
- /* If the key was not a command, put the character in the */
- /* transmit queue. If the character is a carriage return, */
- /* append a line feed to it just in case. */
-
- else
- {
- ComPutc(com, (char)key);
- if(indx.echo)
- put_ch((char)key);
- CheckStatus();
- CheckError();
- }
- }
- }
-
-
- /*
- //-------------------------------------
- //
- // Modified putch()
- //
- //-------------------------------------
- */
- void put_ch(char c)
- {
-
- gotoxy(x, y);
- putch(c);
-
- if(c == '\r' && indx.lf)
- putch('\n');
-
- if(c == '\b')
- printf(" \b");
-
- x = wherex();
- y = wherey();
-
- #ifdef M_I86
- if(x == 1 && y == 25)
- _scrolltextwindow(1);
- #endif
- }
-
-
- /*
- //-------------------------------------
- //
- // Initialize
- //
- //-------------------------------------
- */
- void Init(void)
- {
- FILE *fp;
-
-
-
- /* If an initialization file exists, load it. */
-
- fp = fopen("comdemo.ini", "rb");
- if(fp)
- fread(&indx, sizeof(struct indx), 1, fp);
-
-
-
- /* Set up the screen */
-
- clrscr();
- textattr(BLUE|(LIGHTGRAY<<4));
- gotoxy(1,25);
- cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %2s │"
- " no errors │ CTS= DSR= RI= DCD= ",
- msg.id[indx.id],
- msg.baud[indx.baud],
- msg.mode[indx.mode],
- msg.ansi[indx.ansi],
- msg.hndshk[indx.hndshk],
- msg.lf[indx.lf]);
-
-
- /* Initialize the serial port to the default parameters, */
- /* set the timeout and set the DTR and RTS lines. */
-
- com = ComOpen(id[indx.id], baud[indx.baud], mode[indx.mode], RCVQ, TXQ);
-
-
- /* restore the normal screen */
-
- textattr(LIGHTGRAY);
- window(1,1,80,24);
- }
-
-
- /*
- //-------------------------------------
- //
- // terminate
- //
- //-------------------------------------
- */
- void Uninit(void)
- {
- FILE *fp;
-
-
- /* Store the present parameters in an .ini file so the program */
- /* will remember next time it is executed. */
-
- fp = fopen("comdemo.ini", "wb");
- if(fp)
- fwrite(&indx, sizeof(struct indx), 1, fp);
-
-
- ComClose(com);
- system("cls");
- puts("\n╒═════════════════════════════════════════════════════════════════════════════╕"
- "\n│ Cport v2.0 - Copyright (c) 1993 Bri Productions │"
- "\n├─────────────────────────────────────────────────────────────────────────────┤"
- "\n│ Bri Productions, P.O. Box 7121, Fremont, CA 94537-7121, USA, (510) 794-0616 │"
- "\n╘═════════════════════════════════════════════════════════════════════════════╛"
- );
- exit(0);
- }
-
-
- /*
- //-------------------------------------
- //
- // new parameter
- //
- //-------------------------------------
- */
- void NewParam(void)
- {
-
- /* Update the status line with the new parameters */
-
- window(1,25, 80, 25);
- textattr(BLUE|(LIGHTGRAY<<4));
- cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %s │",
- msg.id[indx.id],
- msg.baud[indx.baud],
- msg.mode[indx.mode],
- msg.ansi[indx.ansi],
- msg.hndshk[indx.hndshk],
- msg.lf[indx.lf]);
-
-
- /* restore the normal screen */
-
- textattr(attrib);
- window(1,1,80,24);
- gotoxy(x, y);
- }
-
-
- /*
- //-------------------------------------
- //
- // ansi control sequence
- //
- //-------------------------------------
- */
- void Ansi(void)
- {
- unsigned key;
- char c;
- char str[10];
- int Pn[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- int i=0,p=0;
- static int oldx=1;
- static int oldy=1;
-
-
- /* While we are waiting for the next character, keep */
- /* checking for keys. */
-
-
- while((c = ComGetc(com)) == 0)
-
- if(bioskey(1))
- {
- key = bioskey(0);
- ComPutc(com, (char)key);
- }
-
-
- /* If the next character is a '[' it is probably an ansi */
- /* sequence. If the next character is not a '[', print the */
- /* previous escape character followed by the new character. */
-
- if(c != '[')
- {
- cprintf("\x1b%c",c);
- return;
- }
-
- while(1)
- {
-
- /* Read the rest of the ansi sequence, while also checking */
- /* for keys. */
-
- while((c = ComGetc(com)) == 0)
-
- if(bioskey(1))
- {
- key = bioskey(0);
- ComPutc(com, (char)key);
- }
-
-
- /* If the character is numeric, store it still it it's */
- /* ascii form */
-
- if(isdigit(c))
- {
- *(str+i++) = c;
- continue;
- }
-
-
- /* When no more numeric characters are received, terminate */
- /* the string and convert it to an integer, storing it in */
- /* the parameter queue. */
-
- *(str+i) = '\0';
- i=0;
- Pn[p++] = atoi(str);
-
-
- /* Check for the ';' delimiter */
-
- if(c == ';')
- continue;
-
-
- /* When no more numeric parameters are received, the */
- /* command should be next. Now we can actually process */
- /* the command using the stores parameters */
-
- else
- {
- switch(c)
- {
-
-
- /* (CUP) set cursor position */
-
- case 'H':
- case 'F':
- y = Pn[0] ? Pn[0] : 1;
- x = Pn[1] ? Pn[1] : 1;
- return;
-
-
- /* (CUU) cursor up */
-
- case 'A':
- y -= Pn[0];
- if(y < 1)
- y = 1;
- return;
-
-
- /* (CUD) cursor down */
-
- case 'B':
- y += Pn[0];
- if(y > 24)
- y = 24;
- return;
-
-
- /* (CUF) cursor forward */
-
- case 'C':
- x += Pn[0];
- if(x >80)
- x = 80;
- return;
-
-
- /* (CUB) cursor backward */
-
- case 'D':
- x -= Pn[0];
- if(x < 1)
- x = 1;
- return;
-
-
- /* (SCP) save cursor position */
-
- case 's':
- oldx = x;
- oldy = y;
- return;
-
-
- /* (RCP) restore cursor position */
-
- case 'u':
- x = oldx;
- y = oldy;
- return;
-
-
- /* clear screen */
-
- case 'J':
- if(Pn[0] == 2)
- {
- clrscr();
- x=1;
- y=1;
- }
- else
- {
- window(1,wherey(),80,24);
- clrscr();
- window(1,1,80,24);
- gotoxy(x, y);
- }
- return;
-
-
- /* (EL) erase line */
-
- case 'K':
- clreol();
- return;
-
-
- /* An attribute command is more elaborate than the */
- /* others because it may have many numeric parameters */
-
- case 'm':
- for(i=0; i<p; i++)
- {
-
-
- /* values from 30 to 37 define the foreground color */
-
- if(Pn[i] >= 30 && Pn[i] <= 37)
- {
- attrib &= 0xf8;
- attrib |= (Pn[i] - 30);
- }
-
-
- /* values from 40 to 47 define the background color */
-
- if(Pn[i] >= 40 && Pn[i] <= 47)
- {
- attrib &= 0x8f;
- attrib |= ((Pn[i] - 40) << 4);
- }
-
-
- /* values from 0 to 7 define the other attributes */
-
- if(Pn[i] >= 0 && Pn[i] <= 7)
- switch(Pn[i])
- {
-
- case 0:
- attrib = NORM;
- break;
-
- case 1:
- attrib |= BOLD;
- break;
-
- case 2:
- attrib &= FAINT;
- break;
-
- case 5:
- case 6:
- attrib |= BLINK;
- break;
-
- case 7:
- attrib ^= REVRS;
- break;
-
- default:
- attrib = NORM;
- }
- }
-
-
- /* The red and blue bits in the ansi standard are */
- /* reversed relative to the IBM. Therefore, before we */
- /* set the new attributes, if these bits are in */
- /* opposite states toggled. This must be done for */
- /* both the foreground and background. */
-
- if((attrib & 0x05) == 0x04 || (attrib & 0x05) == 0x01)
- attrib ^= 0x05;
-
- if((attrib & 0x50) == 0x40 || (attrib & 0x50) == 0x10)
- attrib ^= 0x50;
-
- textattr(attrib);
-
- default:
- return;
- }
- }
- }
- }
-
-
- /*
- //-------------------------------------
- //
- // check for errors
- //
- //-------------------------------------
- */
- void CheckError(void)
- {
- unsigned comerror;
- static unsigned last_error = 0;
- static int err_flg = 0;
- char *errmsg[]= { { "no errors " },
- { "break detect " },
- { "frame error " },
- { "parity error " },
- { "overrun " },
- { "rx overflow " },
- { "tx overflow " }
- };
-
- comerror = ComError(com);
-
-
- /* Check if the error code has changed since the last call. */
- /* if it has not, there is no need to update the status line. */
- /* If the error code has changed, the error conditions are */
- /* checked in the order of their priority */
-
- if(comerror != last_error)
- {
- last_error = comerror;
-
- if(comerror & BREAK)
- err_flg = 1;
-
- else if(comerror & FRAMING)
- err_flg = 2;
-
- else if(comerror & PARITY)
- err_flg = 3;
-
- else if(comerror & OVERUN)
- err_flg = 4;
-
- else if(comerror & RXFULL)
- err_flg = 5;
-
- else if(comerror & TXFULL)
- err_flg = 6;
-
- else
- err_flg = 0;
-
-
- /* Update the status line with the new information */
-
- window(1,25, 80, 25);
- textattr(BLUE|(LIGHTGRAY<<4));
- gotoxy(ERR_X,1);
- cprintf(errmsg[err_flg]);
-
-
- /* restore the normal screen */
-
- textattr(attrib);
- window(1,1,80,24);
- gotoxy(x, y);
- }
- }
-
-
- /*
- //-------------------------------------
- //
- // check modem status
- //
- //-------------------------------------
- */
- void CheckStatus(void)
- {
- unsigned status;
- static unsigned last_status = 1;
- int i;
-
- status = ComStatus(com);
-
-
- /* Check if the modem status has changed since the last call. */
- /* if it has not, there is no need to update the status line. */
- /* If the modem status has changed, each bit is checked for */
- /* it's condition and printed on the status line */
-
- if(status != last_status)
- {
- last_status = status;
- window(1,25, 80, 25);
- textattr(BLUE|(LIGHTGRAY<<4));
-
-
- /* On each iteration, i = the x coordinate in the status */
- /* line. The bits are checked for left to right. The */
- /* statement !!(status & 0x10) resolves to 1 if the bit */
- /* is set or 0 if the bit is clear. By adding 0x30 the */
- /* 1 or 0 is converted to an ascii character */
-
- for(i=STAT_X; i<STAT_X+6*4; i+=6)
- {
- gotoxy(i,1);
- cprintf("%c", !!(status & 0x10) + 0x30);
- status >>= 1;
- }
-
-
- /* restore the normal screen */
-
- textattr(attrib);
- window(1,1,80,24);
- gotoxy(x, y);
- }
- }
-
-
- /*
- //-------------------------------------
- //
- // Upload a file
- //
- //-------------------------------------
- */
- void Upload(void)
- {
- char filename[83];
- int rv;
-
- cputs("\r\n");
- x = wherex();
- y = wherey();
-
- *filename = 80;
- cputs("File name > ");
- cgets(filename);
-
- rv = XmodemTx(com, filename + 2, callback);
-
- clreol();
- cputs(*(Xmsg + rv));
-
- cputs("\r\n");
- x = wherex();
- y = wherey();
- }
-
-
- /*
- //-------------------------------------
- //
- // Download a file
- //
- //-------------------------------------
- */
- void Download(void)
- {
- char filename[83];
- int rv;
-
-
- cputs("\r\n");
- x = wherex();
- y = wherey();
-
- *filename = 80;
- cputs("File name for your computer > ");
- cgets(filename);
-
- rv = XmodemRx(com, filename + 2, callback);
-
- clreol();
- cputs(*(Xmsg + rv));
-
- cputs("\r\n");
- x = wherex();
- y = wherey();
-
- }
-
-
- /*
- //-------------------------------------
- //
- // Xmodem callback function
- //
- //-------------------------------------
- */
- int callback(int msg, XPARAM param)
- {
- static retry = 10;
- const char *_err_txt;
- static const char *err_txt[] = {
- "OVER RUN",
- "BAD BLOCK",
- "BAD BLOCK CHECK",
- "TIME OUT",
- "TRANSFER CANCELED"
- };
-
- switch(msg)
- {
- case XM_IDLE:
- break;
-
- case XM_START:
- cprintf("\r\nWaiting...");
- break;
-
- case XM_BLOCKCHECK:
- cprintf("\r\nblock check:%s\r\n", param == 0 ? "CHECKSUM" : "CRC");
- break;
-
- case XM_BLOCK:
- if(retry < 10)
- {
- retry = 10;
- putchar('\n');
- }
- cprintf("\rblock:%d bytes: %ld", param, ((long)param) << 7);
- break;
-
- case XM_EOT:
- cprintf("\r\nEOT");
- break;
-
- case XM_DONE:
- break;
-
- case XM_ERROR:
- if(param & OVERUN)
- _err_txt = err_txt[0];
- else
- _err_txt = err_txt[param >> 12];
- cprintf("\r\nERROR:%s", _err_txt);
- if(retry-- == 0)
- return(1);
- }
-
- if(kbhit())
- {
- if(getch() == 0x1b)
- return(1);
- }
- return(0);
- }
-
-
-
- /*
- //-------------------------------------
- //
- // Microsoft portability
- //
- //-------------------------------------
- */
- #if M_I86
-
-
- int wherex(void)
- {
- byte rv;
-
- _asm {
- mov bh,0
- mov ah,3
- int 10h
- inc dl
- mov rv,dl
- }
- return(rv);
- }
-
- int wherey(void)
- {
- byte rv;
-
- _asm {
- mov bh,0
- mov ah,3
- int 10h
- inc dh
- mov rv,dh
- }
- return(rv);
- }
-
- void delay (clock_t milliseconds)
- {
- milliseconds += clock();
- while(clock() < milliseconds);
- }
-
- void clreol(void)
- {
- cprintf("%*c", 80 - wherex() - 1, ' ');
- }
-
- int cprintf(const char *fmt, ...)
- {
- va_list list;
- int rv;
- char buf[129];
-
- va_start(list, fmt);
- rv = vsprintf(buf, fmt, list);
- va_end(list);
- _outtext(buf);
- return(rv);
- }
-
- #endif
-
-